home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’95 / Menu Controls / UShapeView.cp < prev    next >
Encoding:
Text File  |  1995-06-24  |  17.2 KB  |  635 lines  |  [TEXT/MPS ]

  1. // UDrawShapes.cp
  2. // Copyright © 1994-95 by Apple Computer, Inc. All rights reserved.
  3.  
  4. #ifndef __USHAPEVIEW__
  5. #include "UShapeView.h"
  6. #endif
  7.  
  8. // MacApp
  9.  
  10. #ifndef __UCLIPBOARDMGR__
  11. #include <UClipboardMgr.h>
  12. #endif
  13.  
  14. #ifndef __UMEMORY__
  15. #include <UMemory.h>
  16. #endif
  17.  
  18. #ifndef __UMENUMGR__
  19. #include <UMenuMgr.h>
  20. #endif
  21.  
  22. #ifndef __UPRINTING__
  23. #include <UPrinting.h>
  24. #endif
  25.  
  26. #ifndef __UMACAPPUTILITIES__
  27. #include <UMacAppUtilities.h>
  28. #endif
  29.  
  30. // Toolbox
  31.  
  32. #ifndef __PICKER__
  33. #include <Picker.h>
  34. #endif
  35.  
  36. #ifndef __TOOLUTILS__
  37. #include <ToolUtils.h>
  38. #endif
  39.  
  40. // DrawShapes
  41.  
  42. #ifndef __SHAPECOMMANDS__
  43. #include "ShapeCommands.h"
  44. #endif
  45.  
  46. #ifndef __TOOLSMENU__
  47. #include "ToolsMenu.h"
  48. #endif
  49.  
  50. #ifndef __UDRAWSHAPES__
  51. #include "UDrawShapes.h"
  52. #endif
  53.  
  54. #ifndef __UPICTSHAPE__
  55. #include "UPictShape.h"
  56. #endif
  57.  
  58. #ifndef __USHAPES__
  59. #include "UShapes.h"
  60. #endif
  61.  
  62. #ifndef __USHAPESDOCUMENT__
  63. #include "UShapesDocument.h"
  64. #endif
  65.  
  66. #ifndef __UTEXTSHAPE__
  67. #include "UTextShape.h"
  68. #endif
  69.  
  70. //----------------------------------------------------------------------------------------
  71. // Resources
  72.  
  73. #define kPickerPrompt        256
  74.  
  75. // Menus
  76. const short mColor            = 7;            // the Color menu resource id
  77.  
  78. //--------------------------------------------------------------------------------------------------
  79. // Data types used for storing shapes in the Desk Scrap
  80.  
  81.     struct ShapeClipRecord {
  82.         short        theNumberOfShapes;
  83.         CRect        theBoundingBox;
  84.         ShapeData    theShapes[1536];
  85.         };
  86.  
  87. typedef ShapeClipRecord* PShapesOnClipboard;
  88. typedef PShapesOnClipboard* ShapesOnClipboard;
  89.  
  90. //========================================================================================
  91. // CLASS TShapeView
  92. //========================================================================================
  93. #undef Inherited
  94. #define Inherited TView
  95.  
  96. #pragma segment AInit
  97. MA_DEFINE_CLASS_M1(TShapeView, Inherited);
  98.  
  99. //----------------------------------------------------------------------------------------
  100. // TShapeView Constructor
  101. //----------------------------------------------------------------------------------------
  102. #pragma segment AOpen
  103.  
  104. TShapeView::TShapeView()
  105. {
  106.     fDragging = false;
  107.     fShapeDocument = NULL;
  108.     fClickPt = gZeroPt;
  109. }
  110.  
  111. //----------------------------------------------------------------------------------------
  112. // TShapeView::IShapeView: 
  113. //----------------------------------------------------------------------------------------
  114. #pragma segment AOpen
  115.  
  116. void TShapeView::IShapeView(TShapeDocument* itsDocument, Boolean forClipboard)
  117. {
  118.     VPoint itsLocation;
  119.     VPoint itsSize;
  120.     SizeDeterminer sd;
  121.  
  122.     SetVPt(itsSize, kMaxCoord, kMaxCoord);
  123.     if (forClipboard)
  124.         sd = sizeVariable;
  125.     else
  126.         sd = sizeFillPages;
  127.     this->IView(itsDocument, NULL, gZeroVPt, itsSize, sd, sd);
  128.  
  129.     fShapeDocument = itsDocument;
  130.  
  131.     if (!forClipboard)
  132.     {
  133.         TStdPrintHandler* printHandler = new TStdPrintHandler;
  134.         printHandler->IStdPrintHandler(itsDocument, this, !kSquareDots, kFixedSize, kFixedSize);
  135.     }
  136. }
  137.  
  138. //----------------------------------------------------------------------------------------
  139. // TShapeView::DoPostCreate: 
  140. //----------------------------------------------------------------------------------------
  141. #pragma segment AOpen
  142.  
  143. void TShapeView::DoPostCreate(TDocument* itsDocument)    // Override
  144. {
  145.     Inherited::DoPostCreate(itsDocument);
  146.     fShapeDocument = (TShapeDocument*)itsDocument;
  147.  
  148.     this->AddAdorner(gSelectionAdorner, kDrawView, false);
  149. }
  150.  
  151. //----------------------------------------------------------------------------------------
  152. // TShapeView::CalcMinFrame: 
  153. //----------------------------------------------------------------------------------------
  154. #pragma segment AOpen
  155.  
  156. void TShapeView::CalcMinFrame(VRect& minFrame) // Override
  157. {
  158.     short numberOfShapes;
  159.     CRect aRect;
  160.     VPoint minSize;
  161.  
  162.     Inherited::CalcMinFrame(minFrame);
  163.  
  164.     fShapeDocument->SurveyShapes(false, numberOfShapes, aRect);
  165.     minFrame.right = minFrame.left + Max(100, aRect.right);
  166.     minFrame.bottom = minFrame.top + Max(100, aRect.bottom);
  167. }
  168.  
  169. //----------------------------------------------------------------------------------------
  170. // TShapeView::ContainsClipType: 
  171. //----------------------------------------------------------------------------------------
  172. #pragma segment ShapeRes
  173.  
  174. Boolean TShapeView::ContainsClipType(ResType aType) // Override
  175. {
  176.     return (aType == kShapeClipType);
  177. }
  178.  
  179. //----------------------------------------------------------------------------------------
  180. // TShapeView::Deselect: 
  181. //----------------------------------------------------------------------------------------
  182. #pragma segment ShapeRes
  183.  
  184. void TShapeView::Deselect()
  185. {
  186.     this->DoHighlightSelection(hlOn, hlOff);
  187.  
  188.     fShapeDocument->DeselectShapes();
  189. }
  190.  
  191. //----------------------------------------------------------------------------------------
  192. // TShapeView::DoHighlightSelection: 
  193. //----------------------------------------------------------------------------------------
  194. #pragma segment ShapeRes
  195.  
  196. void TShapeView::DoHighlightSelection(HLState fromHL, HLState toHL) // Override
  197. {
  198.     fShapeDocument->HiliteShapes(this, fromHL, toHL);
  199. }
  200.  
  201. //----------------------------------------------------------------------------------------
  202. // TShapeView::DoMenuCommand: 
  203. //----------------------------------------------------------------------------------------
  204. #pragma segment ASelCommand
  205.  
  206. void TShapeView::DoMenuCommand(CommandNumber aCommandNumber) // Override
  207. {
  208.     switch (aCommandNumber)
  209.     {
  210.         case cCut:
  211.         case cCopy:
  212.             {
  213.             TShapeCutCopyCommand* shapeCutCopyCommand = new TShapeCutCopyCommand;
  214.             shapeCutCopyCommand->IShapeCutCopyCommand(aCommandNumber, this);
  215.             this->PostCommand(shapeCutCopyCommand);
  216.             }
  217.             break;
  218.  
  219.         case cPaste:
  220.             {
  221.             TShapePasteCommand* shapePasteCommand = new TShapePasteCommand;
  222.             shapePasteCommand->IShapePasteCommand(this);
  223.             this->PostCommand(shapePasteCommand);
  224.             }
  225.             break;
  226.  
  227.         case cClear:
  228.             {
  229.             TShapeClearCommand* shapeClearCommand = new TShapeClearCommand;
  230.             shapeClearCommand->IShapeClearCommand(this);
  231.             this->PostCommand(shapeClearCommand);
  232.             }
  233.             break;
  234.  
  235. #if qDebug
  236.         case cRecalcExtent:
  237.             this->AdjustFrame();
  238.             break;
  239. #endif
  240.  
  241.         case cSelectAll:
  242.             if (this->Focus())
  243.                 this->SelectAllShapes();
  244.             break;
  245.  
  246.         case cPickColor:
  247.             this->PickColor();
  248.             break;
  249.  
  250.         case cBetterFeedback:
  251.             gBetterFeedback = !gBetterFeedback;
  252.             break;
  253.  
  254.         default:
  255.             if (!this->IsMenuColor(aCommandNumber))
  256.                 Inherited::DoMenuCommand(aCommandNumber);
  257.     }
  258. }
  259.  
  260. //----------------------------------------------------------------------------------------
  261. // TShapeView::DoMouseCommand: 
  262. //----------------------------------------------------------------------------------------
  263. #pragma segment ASelCommand
  264.  
  265. void TShapeView::DoMouseCommand(VPoint& theMouse,
  266.                                 TToolboxEvent* event,
  267.                                 CPoint /*hysteresis*/) // Override
  268. {
  269.     TToolsPalette* palette = GetToolsPalette();
  270.     CPoint qdPt = ViewToQDPt(theMouse);
  271.     fClickPt = qdPt;
  272.     short currentTool = palette->GetCurrTool();
  273.     if (currentTool > 0)                    // draw mode
  274.     {
  275.         FailSpaceIsLow();                    // Make sure we aren't low on memory
  276.         this->Deselect();
  277.  
  278.         // Clone appropriate shape
  279.         TShape* shape = GetShapeInArray(currentTool);
  280.         FailNonObject(shape);
  281.         
  282.         MAVolatileInit(TShape*, protoShape, (TShape*)shape->Clone());
  283.         FailInfo fi;
  284.  
  285.         Try(fi)
  286.         {
  287.             // Make sure cloning the shape left us with enough memory to continue.
  288.             FailSpaceIsLow();
  289.     
  290.             TShapeSketcher* shapeSketcher = new TShapeSketcher;
  291.             shapeSketcher->IShapeSketcher(this, protoShape, theMouse, event->IsOptionKeyPressed());
  292.             fi.Success();
  293.             this->PostCommand(shapeSketcher);
  294.         }
  295.         else
  296.         {
  297.             FreeIfObject(protoShape);
  298.             fi.ReSignal();
  299.         }
  300.     }
  301.     else                                    // select mode
  302.     {
  303.         TShape* shapeUnderMouse = fShapeDocument->ShapeUnderMouse(qdPt);
  304.         if (shapeUnderMouse == NULL)        // area select
  305.         {
  306.             if (!event->IsShiftKeyPressed())
  307.                 this->Deselect();
  308.             TShapeSelector* shapeSelector = new TShapeSelector;
  309.             shapeSelector->IShapeSelector(cMouseCommand, this, theMouse);
  310.             this->PostCommand(shapeSelector);
  311.         }
  312.         else                                // shape select/move/...
  313.         {
  314.             if (!(shapeUnderMouse->IsSelected() || event->IsShiftKeyPressed()))
  315.                 this->Deselect();
  316.  
  317.             if (event->IsShiftKeyPressed())
  318.             {
  319.                 shapeUnderMouse->SetSelected(!shapeUnderMouse->IsSelected());
  320.                 if (shapeUnderMouse->IsSelected())
  321.                     shapeUnderMouse->Highlight(hlOff, hlOn, this);
  322.                 else
  323.                     shapeUnderMouse->Highlight(hlOn, hlOff, this);
  324.             }
  325.             else if (!shapeUnderMouse->IsSelected())
  326.             {
  327.                 shapeUnderMouse->SetSelected(true);
  328.                 this->DoHighlightSelection(hlOff, hlOn);
  329.             }
  330.  
  331.             if (shapeUnderMouse->IsSelected())
  332.             {
  333.                 TShapeDragger* shapeDragger = new TShapeDragger;
  334.                 shapeDragger->IShapeDragger(this, theMouse);
  335.                 this->PostCommand(shapeDragger);
  336.             }
  337.         }
  338.     }
  339. }
  340.  
  341. //----------------------------------------------------------------------------------------
  342. // TShapeView::DoSetupMenus
  343. //----------------------------------------------------------------------------------------
  344. #pragma segment ARes
  345.  
  346. void TShapeView::DoSetupMenus() // Override
  347. {
  348.     Inherited::DoSetupMenus();
  349.  
  350.     Boolean anySelection = false;
  351.     Boolean anyShapes = false;
  352.  
  353.     // Find out if we are low on memory. If we are then we'll disable all
  354.     // memory-intensive commands.
  355.     Boolean haveMemory = !MemSpaceIsLow();
  356.  
  357.     // Check every virtual shape
  358.     fShapeDocument->AnyShapesSelected(anySelection, anyShapes);
  359.  
  360.     // Enable the Patterns menu if there is a selection
  361.     Enable(cPatterns, anySelection);
  362.  
  363.     if (anySelection && (qNeedsColorQD || gConfiguration.hasColorQD))
  364.     {
  365.         // Enable each of the Color menu items, if the Color menu is present
  366.         MenuHandle aMenuHandle = GetMenuHandle(mColor);
  367.         if (aMenuHandle)
  368.         {
  369.             short itemCount = CountMItems(aMenuHandle);
  370.             for (short item = 1; item <= itemCount; item++)
  371.             {
  372.             // There can be more than 31 menu entries with scrolling menus, 
  373.             // but trying to enable an item with number > 31 is bad news.
  374.             // If the menu itself is enabled (which it will be in MacApp
  375.             // if any of the first 31 items is enabled), then the extras
  376.             // will always be enabled.
  377.                 // Don't enable line separators
  378.                 CStr255 itemName;
  379.                 GetMenuItemText(aMenuHandle, item, itemName);
  380.                 if (item <= 31 && itemName != "-")
  381.                     EnableItem(aMenuHandle, item);
  382.             }
  383.         }
  384.     }
  385.  
  386. #if qDebug
  387.     Enable(cRecalcExtent, true);
  388. #endif
  389.     Enable(cCut, anySelection && haveMemory);
  390.     Enable(cCopy, anySelection && haveMemory);
  391.     if (haveMemory)
  392.     {
  393.         gClipboardMgr->CanPaste(kShapeClipType);
  394.         gClipboardMgr->CanPaste('PICT');
  395.         gClipboardMgr->CanPaste('TEXT');
  396.     }
  397.     Enable(cClear, anySelection);
  398.  
  399.     Enable(cSelectAll, anyShapes);
  400.     EnableCheck(cBetterFeedback, true, gBetterFeedback);
  401. }
  402.  
  403. //----------------------------------------------------------------------------------------
  404. // TShapeView::DoSetCursor
  405. //----------------------------------------------------------------------------------------
  406. #pragma segment ShapeRes
  407.  
  408. void TShapeView::DoSetCursor(const VPoint& localPoint, RgnHandle cursorRegion) // Override
  409. {
  410.     CPoint qdPoint = ViewToQDPt(localPoint);
  411.     TToolsPalette* palette = GetToolsPalette();
  412.     short currentTool = palette->GetCurrTool();
  413.  
  414.     if (currentTool == 0)                        // Selection
  415.     {
  416.         Boolean cursorSet = fShapeDocument->CursorInShape(qdPoint, cursorRegion);
  417.         if (!cursorSet)
  418.         {
  419.             if (qNeedsColorQD || gConfiguration.hasColorQD)
  420.                 SetCCursor(gRainbowArrow);        // set cursor to color arrow
  421.             else
  422.                 SetCursor(&qd.arrow);
  423.         }
  424.     }
  425.     else
  426.     {
  427.         UseROMMap(true);
  428.         SetCursor(*GetCursor(crossCursor));
  429.         CRect qdExtent;
  430.         GetQDExtent(qdExtent);
  431.         RectRgn(cursorRegion, qdExtent);
  432.     }
  433. }
  434.  
  435. //----------------------------------------------------------------------------------------
  436. // TShapeView::Draw
  437. //----------------------------------------------------------------------------------------
  438. #pragma segment ARes
  439.  
  440. void TShapeView::Draw(const VRect& area) // Override
  441. {
  442.     CRect qdArea;
  443.     ViewToQDRect(area, qdArea);
  444.     fShapeDocument->DrawShapes(qdArea, fDragging);
  445.  
  446.     Inherited::Draw(area);
  447. }
  448.  
  449. //----------------------------------------------------------------------------------------
  450. // TShapeView::InvalShape
  451. //----------------------------------------------------------------------------------------
  452. #pragma segment ShapeRes
  453.  
  454. void TShapeView::InvalShape(TShape* aShape)
  455. {
  456.     CRect r;
  457.     aShape->GetFrame(r);
  458.     InsetRect(r, -2, -2);
  459.     InvalidateRect(r);
  460. }
  461.  
  462. //----------------------------------------------------------------------------------------
  463. // TShapeView::RestoreSelection
  464. //----------------------------------------------------------------------------------------
  465. #pragma segment ShapeRes
  466.  
  467. void TShapeView::RestoreSelection()
  468. {
  469.     this->Focus();
  470.     this->Deselect();
  471.  
  472.     fShapeDocument->RestoreSelection(this);
  473. }
  474.  
  475. //----------------------------------------------------------------------------------------
  476. // TShapeView::SaveSelection
  477. //----------------------------------------------------------------------------------------
  478. #pragma segment ShapeRes
  479.  
  480. void TShapeView::SaveSelection(Boolean andInval)
  481. {
  482.     this->Focus();
  483.  
  484.     fShapeDocument->SaveSelection(this, andInval);
  485. }
  486.  
  487. //----------------------------------------------------------------------------------------
  488. // TShapeView::WriteToDeskScrap
  489. //----------------------------------------------------------------------------------------
  490. #pragma segment AClipboard
  491.  
  492. void TShapeView::WriteToDeskScrap() // Override
  493. {
  494.     short count;
  495.     CRect bBox;
  496.     short wantBytes;    // long???
  497.     PShapesOnClipboard clipShapes;    //  pointer to a ShapeClipRecord
  498.  
  499.     // Write the PICT scrap first in case we will be unable to write both 
  500.     // the PICT scrap and our own scrap type.
  501.     Inherited::WriteToDeskScrap();                        // Generate PICT-type scrap
  502.  
  503.     fShapeDocument->SurveyShapes(false, count, bBox);    // count shapes
  504.     wantBytes = sizeof(short) + sizeof(Rect) + (count * sizeof(ShapeData));
  505.     ShapeClipRecord** shapeClipRecHandle = (ShapeClipRecord**)NewPermHandle(wantBytes);
  506.     clipShapes = *shapeClipRecHandle;
  507.     clipShapes->theBoundingBox = bBox;
  508.     clipShapes->theNumberOfShapes = count;
  509.  
  510.     // Copy each shape to the desk scrap
  511.     short i = 0;
  512.     CShapeIterator iter(fShapeDocument->GetShapeList());
  513.     for (TShape* shape = iter.FirstShape(); iter.More(); shape = iter.NextShape())
  514.     {
  515.         ShapeData aShapeDatum;
  516.         aShapeDatum.theId = shape->GetID();
  517.         aShapeDatum.thePattern = shape->GetPattern();
  518.         shape->GetColor(aShapeDatum.theColor);
  519.         CRect extent;
  520.         shape->GetFrame(extent);
  521.         aShapeDatum.theRect = extent;
  522.         clipShapes->theShapes[i] = aShapeDatum;
  523.         i++;
  524.     }
  525.  
  526.     OSErr err = gClipboardMgr->PutDeskScrapData(kShapeClipType, (Handle)shapeClipRecHandle);
  527.     DisposeIfHandle((Handle)shapeClipRecHandle);
  528.     FailOSErr(err);
  529. }
  530.  
  531. //----------------------------------------------------------------------------------------
  532. // TShapeView::ReadFromDeskScrap
  533. //    Launch a view to represent the data found in the Clipboard at application start-up 
  534. //    time, or when switching back in, or when returning from a Desk Accessory.
  535. //----------------------------------------------------------------------------------------
  536. #pragma segment AClipboard
  537.  
  538. void TShapeView::ReadFromDeskScrap()
  539. {
  540.     MAVolatileInit(ShapesOnClipboard, clipShapes, NULL);
  541.     
  542.     FailInfo fi;
  543.     Try(fi)
  544.     {
  545.         clipShapes = (ShapesOnClipboard)NewPermHandle(0);
  546.         FailSpaceIsLow();
  547.  
  548.         Boolean perm = PermAllocation(true);
  549.         long offset;
  550.         long result;
  551.         result = GetScrap((Handle)clipShapes, kShapeClipType, &offset);
  552.         PermAllocation(perm);
  553.  
  554.         // Only a negative result indicates an error,
  555.         // but FailOSErr considers any non-zero result an error.
  556.         if (result < 0) FailOSErr((OSErr)result);
  557.  
  558.         // Read the shapes from the clipboard and add them to the document
  559.         short shapeCount = (*clipShapes)->theNumberOfShapes;
  560.         for (short i=0; i < shapeCount; i++)
  561.         {
  562.             ShapeDataPtr p = (ShapeDataPtr) &(*clipShapes)->theShapes[i];
  563.             TShape* oldShape = GetShapeInArray(p->theId);
  564.             if (oldShape)
  565.             {
  566.                 TShape* aNewShape = (TShape*)oldShape->Clone();
  567.                 aNewShape->SetFields(p->thePattern, p->theColor, p->theRect);
  568.                 fShapeDocument->AddShape(aNewShape);
  569.             }
  570.         }
  571.         fi.Success();
  572.     }
  573.     else // Recover
  574.     {
  575.         DisposeIfHandle((Handle)clipShapes);
  576.         fi.ReSignal();
  577.     }
  578.     DisposeIfHandle((Handle)clipShapes);
  579. }
  580.  
  581. //----------------------------------------------------------------------------------------
  582. // TShapeView::IsMenuColor
  583. //----------------------------------------------------------------------------------------
  584. #pragma segment ASelCommand
  585.  
  586. Boolean TShapeView::IsMenuColor(CommandNumber aCommandNumber)
  587. {
  588.     short menu;
  589.     short item;
  590.     CommandToMenuItem(aCommandNumber, menu, item);
  591.     if (menu != mColor)
  592.         return false;
  593.  
  594.     MCEntryPtr pMCEntry = GetMCEntry(menu, item);
  595.     CRGBColor theColor = pMCEntry->mctRGB2;
  596.     TRecolorCmd* recolorCmd = new TRecolorCmd;
  597.     recolorCmd->IRecolorCmd(theColor, this);
  598.     this->PostCommand(recolorCmd);
  599.     return true;
  600. }
  601.  
  602. //----------------------------------------------------------------------------------------
  603. // TShapeView::PickColor
  604. //----------------------------------------------------------------------------------------
  605. #pragma segment ASelCommand
  606.  
  607. void TShapeView::PickColor()
  608. {
  609.     CRGBColor theColor;
  610.  
  611.     // Get the color of the first selected shape
  612.     TShape* shape = fShapeDocument->FirstSelectedShape();
  613.     shape->GetColor(theColor);
  614.     StringHandle pickerPrompt = GetString(kPickerPrompt);
  615.     FailNIL(pickerPrompt);
  616.     if (GetColor(CPoint(-1,-1), *pickerPrompt, theColor, theColor))
  617.     {
  618.         TRecolorCmd* recolorCmd = new TRecolorCmd;
  619.         recolorCmd->IRecolorCmd(theColor, this);
  620.         this->PostCommand(recolorCmd);
  621.     }
  622. }
  623.  
  624. //----------------------------------------------------------------------------------------
  625. // TShapeView::SelectAllShapes
  626. //----------------------------------------------------------------------------------------
  627. #pragma segment ASelCommand
  628.  
  629. void TShapeView::SelectAllShapes()
  630. {
  631.     fShapeDocument->SelectAllShapes(this);
  632. }
  633.  
  634.  
  635.